import request from '@/utils/request'; // 导入封装的 request 工具

/**
 * 处理 JSON-RPC 响应，提取数据或抛出错误
 * @param {Object} response Axios 响应对象
 * @returns {Object} 成功响应的 result 部分
 * @throws {Error} 如果响应包含错误
 */
function handleResponse(response) {
  if (response?.data?.error) {
    console.error("API Error:", response.data.error);
    throw new Error(response.data.error.message || 'API 请求失败');
  }
  // 直接返回 result 部分，让调用方处理具体内容
  if ('result' in response?.data) {
      return response.data.result;
  }
  // 未知错误或非预期格式
  console.error("Unexpected API response format:", response?.data);
  throw new Error('API 响应格式错误或非预期结果');
}

/**
 * 上传模型文件
 * @param {Object} params 上传参数
 * @param {number} params.chunk_index 分片索引
 * @param {number} params.total_chunks 总分片数
 * @param {string} params.chunk_data 分片数据(base64编码)
 * @param {Object} params.file_info 文件信息(仅第一个分片需要)
 * @param {string} params.file_info.filename 文件名（唯一标识符）
 * @param {number} params.file_info.size 文件大小
 * @param {string} params.file_info.description 模型描述（可选）
 * @returns {Promise<Object>} 上传结果
 */
export const uploadModel = async (params) => {
  try {
    const response = await request.post('/v1/jsonrpc2/', {
      jsonrpc: '2.0',
      id: 'upload_model_' + Date.now(), // 使用时间戳保证 ID 唯一性
      method: 'model.upload',
      params: params
    });
    return handleResponse(response);
  } catch (error) {
    console.error("上传模型失败:", error);
    throw error instanceof Error ? error : new Error('上传模型失败');
  }
};

/**
 * 获取模型列表
 * @returns {Promise<Array>} 模型列表
 */
export const getModelList = async () => {
  try {
    const response = await request.post('/v1/jsonrpc2/', {
      jsonrpc: '2.0',
      id: 'get_model_list_' + Date.now(),
      method: 'model.list',
      params: {}
    });
    return handleResponse(response);
  } catch (error) {
    console.error("获取模型列表失败:", error);
    throw error instanceof Error ? error : new Error('获取模型列表失败');
  }
};

/**
 * 下载模型
 * @param {string} filename 模型文件名
 * @returns {Promise<Blob>} 返回模型文件的Blob对象
 */
export const downloadModel = async (filename) => {
  try {
    const chunks = [];
    let fileInfo = null;
    let currentChunk = 0;
    
    // 获取第一个分块和文件信息
    const firstChunkResponse = await request.post('/v1/jsonrpc2/', {
      jsonrpc: '2.0',
      id: 'download_model_chunk_0_' + Date.now(),
      method: 'model.download',
      params: {
        filename: filename,
        chunk_index: 0,
        chunk_size: 1048576 // 1MB
      }
    });

    const firstResult = handleResponse(firstChunkResponse);
    if (!firstResult?.file_info) {
      throw new Error('无法获取文件信息');
    }

    fileInfo = firstResult.file_info;
    chunks.push(base64ToUint8Array(firstResult.chunk_data));

    // 下载剩余分块
    for (currentChunk = 1; currentChunk < fileInfo.total_chunks; currentChunk++) {
      const response = await request.post('/v1/jsonrpc2/', {
        jsonrpc: '2.0',
        id: `download_model_chunk_${currentChunk}_` + Date.now(),
        method: 'model.download',
        params: {
          filename: filename,
          chunk_index: currentChunk,
          chunk_size: 1048576
        }
      });

      const result = handleResponse(response);
      if (!result?.chunk_data) {
        throw new Error(`下载分块 ${currentChunk} 失败`);
      }

      chunks.push(base64ToUint8Array(result.chunk_data));
    }

    // 合并所有分块
    const completeFile = new Blob(chunks, { 
      type: getModelMimeType(fileInfo.format) 
    });

    // 验证文件大小
    if (completeFile.size !== fileInfo.size) {
      throw new Error('文件大小不匹配');
    }

    return completeFile;
  } catch (error) {
    console.error('下载模型失败:', error);
    throw error instanceof Error ? error : new Error('下载模型失败');
  }
};

/**
 * 删除模型
 * @param {string} filename 模型文件名
 * @returns {Promise<Object>} 删除结果
 */
export const deleteModel = async (filename) => {
  try {
    const response = await request.post('/v1/jsonrpc2/', {
      jsonrpc: '2.0',
      id: 'delete_model_' + Date.now(),
      method: 'model.delete',
      params: { filename: filename }
    });
    return handleResponse(response);
  } catch (error) {
    console.error("删除模型失败:", error);
    throw error instanceof Error ? error : new Error('删除模型失败');
  }
};

/**
 * 获取模型详细信息
 * @param {string} filename 模型文件名
 * @returns {Promise<Object>} 模型详细信息
 */
export const getModelInfo = async (filename) => {
  try {
    const response = await request.post('/v1/jsonrpc2/', {
      jsonrpc: '2.0',
      id: 'get_model_info_' + Date.now(),
      method: 'model.getInfo',
      params: { filename: filename }
    });
    return handleResponse(response);
  } catch (error) {
    console.error("获取模型信息失败:", error);
    throw error instanceof Error ? error : new Error('获取模型信息失败');
  }
};

/**
 * 将Base64字符串转换为Uint8Array
 * @param {string} base64 Base64编码的字符串
 * @returns {Uint8Array}
 */
function base64ToUint8Array(base64) {
  const binaryString = atob(base64);
  const length = binaryString.length;
  const bytes = new Uint8Array(length);
  
  for (let i = 0; i < length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  
  return bytes;
}

/**
 * 根据模型格式获取MIME类型
 * @param {string} format 模型格式
 * @returns {string} MIME类型
 */
function getModelMimeType(format) {
  const mimeTypes = {
    'onnx': 'application/onnx',
    'bin': 'application/octet-stream',
    'pt': 'application/octet-stream',
    'om': 'application/octet-stream'
  };
  return mimeTypes[format] || 'application/octet-stream';
}

/**
 * 将文件转换为分块数据进行上传
 * @param {File} file 文件对象
 * @param {Function} onProgress 进度回调函数
 * @param {string} description 模型描述（可选）
 * @returns {Promise<Object>} 上传结果
 */
export const uploadModelFile = async (file, onProgress, description = '') => {
  const chunkSize = 1024 * 1024; // 1MB
  const totalChunks = Math.ceil(file.size / chunkSize);
  
  try {
    for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
      const start = chunkIndex * chunkSize;
      const end = Math.min(start + chunkSize, file.size);
      const chunk = file.slice(start, end);
      
      // 将chunk转换为ArrayBuffer然后转为Base64
      const arrayBuffer = await chunk.arrayBuffer();
      const uint8Array = new Uint8Array(arrayBuffer);
      const base64Data = arrayBufferToBase64(uint8Array);
      
      const uploadParams = {
        chunk_index: chunkIndex,
        total_chunks: totalChunks,
        chunk_data: base64Data
      };
      
      // 第一块包含文件信息
      if (chunkIndex === 0) {
        uploadParams.file_info = {
          filename: file.name,
          size: file.size,
          description: description
        };
      }
      
      const result = await uploadModel(uploadParams);
      
      // 调用进度回调
      if (onProgress) {
        const progress = Math.round(((chunkIndex + 1) / totalChunks) * 100);
        onProgress(progress, chunkIndex + 1, totalChunks);
      }
      
      // 如果是最后一块且上传成功，返回结果
      if (chunkIndex === totalChunks - 1) {
        return result;
      }
    }
  } catch (error) {
    console.error("分块上传失败:", error);
    throw error;
  }
};

/**
 * 将ArrayBuffer转换为Base64字符串
 * @param {Uint8Array} uint8Array
 * @returns {string}
 */
function arrayBufferToBase64(uint8Array) {
  let binary = '';
  for (let i = 0; i < uint8Array.byteLength; i++) {
    binary += String.fromCharCode(uint8Array[i]);
  }
  return btoa(binary);
}

